home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / amok_lha / amok17.lha / IFFtoImage / Sources / IFFLoad.mod < prev    next >
Text File  |  1993-08-15  |  23KB  |  662 lines

  1. (*---------------------------------------------------------------------------
  2.     :Program.    IFFLoad.mod
  3.     :Author.     Fridtjof Siebert
  4.     :Address.    Nobileweg 67, D-7-Stgt-40
  5.     :Phone.      0711/822509
  6.     :Shortcut.   [fbs]
  7.     :Version.    1.1
  8.     :Date.       20-May-88
  9.     :Copyright.  Shareware or PD, anyway you like. (I like Shareware better)
  10.     :Language.   Modula-II
  11.     :Translator. M2Amiga
  12.     :Imports.    LoadBody.asm [fbs]
  13.     :UpDate.     07-Jun-88: Maschinensprachteil [fbs]
  14.     :Contents.   Schnelle Ladeprozedur für IFF (ILBM)-Bilder.
  15.     :Remark.     Let's wave! The Cure. The Mission. Sisters of Mercy !!!
  16. ---------------------------------------------------------------------------*)
  17. IMPLEMENTATION MODULE IFFLoad;
  18.  
  19. FROM SYSTEM    IMPORT ADR, ADDRESS, SHIFT, BITSET, LONGSET, CAST, INLINE,
  20.                       REG;
  21.  
  22. FROM Exec      IMPORT AllocMem, FreeMem, MemReqs, MemReqSet, UByte,
  23.                       Interrupt, AddIntServer, RemIntServer, NodeType;
  24. FROM Dos       IMPORT FileHandlePtr, Open, Close, Read, oldFile;
  25. FROM Intuition IMPORT NewScreen, ScreenPtr, OpenScreen, CloseScreen,
  26.                       ScreenToBack, ScreenFlags, ScreenFlagSet,
  27.                       customScreen, MoveScreen, WindowPtr, OpenWindow,
  28.                       CloseWindow, IDCMPFlags, IDCMPFlagSet, WindowFlags,
  29.                       WindowFlagSet;
  30. FROM Graphics  IMPORT SetRGB4, RastPortPtr, BitMapPtr, ViewModes,
  31.                       ViewModeSet, BitMap, InitBitMap, AllocRaster,
  32.                       BltClear, FreeRaster, ViewPortPtr;
  33. FROM GfxMacros IMPORT OffDisplay, OnDisplay;
  34. FROM Hardware  IMPORT vertb;
  35.  
  36. FROM Arts      IMPORT TermProcedure, Assert, CurrentLevel;
  37. FROM Strings   IMPORT Compare, first, last;
  38.  
  39. FROM LoadBody  IMPORT LoadBody;
  40.  
  41. (*---------------------------------------------------------------------------
  42. !                                                                           !
  43. !                        Variables from Definition:                         !
  44. !                                                                           !
  45. -----------------------------------------------------------------------------
  46.  
  47. (*---------------------------  Types:  ------------------------------------*)
  48.  
  49. TYPE
  50.   IFFTitles = (BMHD,CMAP,GRAB,DEST,CAMG,CRNG,BODY,SPRT,CCRT,CMHD,DPPV);
  51.   IFFTitleSet = SET OF IFFTitles;
  52. (* SPRT,CCRT,CMHD,DPPV not implemented !!!                                 *)
  53.  
  54.   ViewTypes = (vt0,Ersy,Lace,LPen,vt4,vt5,vt6,vt7,Gaud,Color,DblPF,HoMod,
  55.                vt12,vt13,vt14,Hires,v16);
  56.   ViewTypeSet = SET OF ViewTypes;
  57. (* which ViewModes are selected *)
  58.  
  59. TYPE
  60.  
  61. (*-------------  The Structure that keeps all the data:  ------------------*)
  62. (* You don't have to understand all variables in this structure! Only some *)
  63. (* are important, like BMHD.width/height or CMAP.red[] etc. The other data *)
  64. (* is used by the Routines that are exported from this module,like DoCycle *)
  65. (* etc.                                                                    *)
  66.  
  67.   IFFInfoTypePtr = POINTER TO IFFInfoType;
  68.   IFFInfoType = RECORD
  69.   (* This contains all Data needed for a Picture *)
  70.  
  71. (*------  Which Data is availble:  ------*)
  72.     IFFTitle: IFFTitleSet;     (* all Sub-Records, whose equally named Flag*)
  73. (* is set here, contain readable data                                      *)
  74.  
  75. (*------  Information on BitMap:  ------*)
  76.     BMHD: RECORD
  77.  
  78.       width,height: INTEGER;   (* the Picture's Size                       *)
  79.       depth: UByte;            (* it's Depth (how many BitPlanes)          *)
  80.       left,top: INTEGER;       (* it's Location                            *)
  81.       masking: UByte;          (* Masking (see Documentation)              *)
  82.       transCol: INTEGER;       (* Transparent Color                        *)
  83.       xAspect,yAspect: UByte;  (* Verzerrung                               *)
  84.       scrnWidth,scrnHeight: INTEGER; (* The Image's Screen's Size          *)
  85.     END;
  86.  
  87. (*------  Information on Colors:  ------*)
  88.     CMAP: RECORD
  89.  
  90.       colorCnt: CARDINAL;      (* Number of Colors used                    *)
  91.       red,green,blue:   ARRAY[0..63] OF UByte;
  92.        (* the Colors (I hope for 6 Bitplanes to be possible anytime)       *)
  93.     END;
  94.  
  95. (*------  Information on HotSpot:  ------*)
  96.     GRAB: RECORD
  97.  
  98.       hotX,hotY: INTEGER;      (* Hot-Spot of this Image (if exists        *)
  99.     END;
  100.  
  101. (*------  Information on Destination-Bitmap:  ------*)
  102.     DEST: RECORD
  103.       depth: UByte;            (* number of Planes                         *)
  104.       planePick: CARDINAL;
  105.       planeOnOff: CARDINAL;    (* set or clear other Planes ?              *)
  106.       planeMask: CARDINAL;     (* planes to be changed                     *)
  107.     END;
  108.  
  109. (*------  Information on any Special ViewMode:  ------*)
  110.     CAMG: RECORD
  111.       viewType: ViewTypeSet;   (* ViewMode                                 *)
  112.     END;
  113.  
  114. (*------  Information on ColorCycling:  ------*)
  115.     CRNG: RECORD
  116.       count: CARDINAL;         (* Number of ColorCyclings                  *)
  117.       data: ARRAY[0..15] OF RECORD
  118.  
  119.         rate: INTEGER;         (* velocity, 800H is 60 per second          *)
  120.         on: BOOLEAN;           (* decide, wether CRNG is active or not     *)
  121.         forward: BOOLEAN;      (* Direction (DPaint)                       *)
  122.         low,high: UByte;       (* lower and upper Color of this Range      *)
  123.       END;
  124.     END;
  125. (*------  Internal Information:  ------*)
  126.     Internal: RECORD
  127.       CycleID: CARDINAL;       (* that's to distinguish different cyclings *)
  128.     END;
  129.   END;
  130.  
  131. (* That's been quite a complex Variable. If you wanna use it, do it this   *)
  132. (* way:                                                                    *)
  133. (* e.g. You wanna know, how Deep your Image is. Ça marche comme ça:        *)
  134. (* MyDepth := IFFInfo.BMHD.depth;                                          *)
  135. (* You can get the speed of the second Colorcycle this way:                *)
  136. (* speed := IFFInfo.CRNG.data[2].rate;                                     *)
  137.  
  138. (*--------------  That's the Variable, that contains all Data  ------------*)
  139. (* this should be imported to your Module to get the Data. Don't forget to *)
  140. (* save the data, e.g. to a variable of the same type. Everytime you load  *)
  141. (* a new IFF-File, the data is scratched !!! (i.e. the new data is written *)
  142. (* into this structure.)                                                   *)
  143.  
  144. VAR
  145.   IFFInfo: IFFInfoType;
  146.  
  147. (*--------------------  The NewScreen-Structure.  -------------------------*)
  148. (* this can be used to open the Screen, if dontopen is specified           *)
  149.  
  150. VAR
  151.   NuScreen: NewScreen;
  152.  
  153. (*--------------------  The NewWindow-Structure.  -------------------------*)
  154. (* this can be used to open the Window later. Don't forget to put Screen-  *)
  155. (* Ptr in NuWindow.screen !!!                                              *)
  156.  
  157. VAR
  158.   NuWindow: NewWindow;
  159.  
  160. *)
  161.  
  162. (*-------------------------------------------------------------------------*)
  163. (*                                                                         *)
  164. (*                     Internal Variables and Types:                       *)
  165. (*                                                                         *)
  166. (*-------------------------------------------------------------------------*)
  167.  
  168. CONST
  169.     MOVEMS = 48E7H; (* that's the 68000-Instruction MOVEM to save Registers*)
  170.     MOVEML = 4CDFH; (* that's MOVEM to load Registers                      *)
  171.  
  172. TYPE
  173.   CyclingInfo = RECORD
  174.     int: Interrupt;   (* The Cycling's Interrupt *)
  175.     VP: ViewPortPtr;  (* The Cycling's ViewPort *)
  176.     count: ARRAY[0..15] OF CARDINAL;   (* counts Cycling-Positions *)
  177.     speedCnt: ARRAY[0..15] OF CARDINAL; (* counts Speed *)
  178.          (* The Cycling-Direction (TRUE=Forwards) *)
  179.   END;
  180.  
  181. VAR
  182.   InH: FileHandlePtr;
  183.   i,j,k: LONGINT;
  184.   length: INTEGER;
  185.   LineLength: LONGINT;         (* Bytes per Image-Line                     *)
  186.   LineWidth: LONGINT;          (* Bytes per Screen-Line                    *)
  187.   BM: BitMapPtr;
  188.   Compression: BOOLEAN;        (* Decide, wether data is compressed or not *)
  189.   MaskPlane: BOOLEAN;          (* Is there a Mask-Plane ??                 *)
  190.   Buffer: ADDRESS;
  191.   TextBuffer: POINTER TO ARRAY[0..63] OF ARRAY[0..3] OF CHAR;
  192.   LONGBuffer: POINTER TO ARRAY[0..63] OF LONGCARD;
  193.   WORDBuffer: POINTER TO ARRAY[0..127] OF INTEGER;
  194.   BYTEBuffer: POINTER TO ARRAY[0..255] OF UByte;
  195.   len: LONGINT;
  196.   BitMaps: ARRAY[0..5] OF ADDRESS;
  197.   Byte,Byte2: UByte;
  198.   Line,Plane: LONGINT;
  199.   Location,Right: POINTER TO UByte;
  200.   RQPos,RQLen: LONGCARD;
  201.   RQBuffer: POINTER TO ARRAY[0..511] OF UByte;
  202.   SpecialView: LONGSET;
  203.   Exit: BOOLEAN;
  204.   NoErr: BOOLEAN;
  205.   CycleInfos: ARRAY[0..31] OF CyclingInfo;
  206.   IntInfo: IFFInfoTypePtr;
  207.   IntNum: CARDINAL;
  208.   IntCount,IntCount2,IntCount3: CARDINAL;
  209.   myLevel:INTEGER;
  210.  
  211. (*-----------  Procedure called by machinecode to get Data:  --------------*)
  212.  
  213. PROCEDURE Read512();
  214.  
  215. BEGIN
  216.   len := Read(InH,RQBuffer,512);
  217. END Read512;
  218.  
  219. (*-------------------------------------------------------------------------*)
  220. (*                                                                         *)
  221. (*                          R e a d  I L B M :                             *)
  222. (*                                                                         *)
  223. (*-------------------------------------------------------------------------*)
  224.  
  225. (*
  226. TYPE
  227.   ReadILBMFlags = (front,visible,dontopen,window);
  228.   ReadILBMFlagSet = SET OF ReadILBMFlags;
  229. *)
  230.  
  231. PROCEDURE ReadILBM(name: ARRAY OF CHAR; Flags: ReadILBMFlagSet;
  232.                    VAR Screen: ScreenPtr; VAR Window: WindowPtr): BOOLEAN;
  233. (* ReadILBM() lädt ein IFF-Bild und öffnet das geladene Bild als Screen.   *)
  234. (* Name: The IFF-Filename                                                  *)
  235. (* Flags:                                                                  *)
  236. (*  -front: decides whether Screen is first or last one while loading      *)
  237. (*  -visible: decides if display should be turned off (that's faster)      *)
  238. (*  -dontopen: avoids to open the Screen. The Returned value is NIL. The   *)
  239. (*     BitMap of the loaded Imagery can be found in NuScreen.customBitMap. *)
  240. (*     Don't forget to free the image's Memory if it's no more needed and  *)
  241. (*     the Memory needed for the BitMap-Structure.                         *)
  242. (*  -window: if set, an Window of the same size as the Image is opened.    *)
  243. (*           So, Gadgets etc. can be added to it.                          *)
  244. (* Screen: Pointer to Screen-structure of opened Screen                    *)
  245. (* Window: Pointer to the opened Window or NIL if window isn't set.        *)
  246. (* Result: FALSE if error occured. Then there's no Screen opened.          *)
  247.  
  248. PROCEDURE OpenScrn();
  249. (* this initializes the Screen, Window and Bitmap, if they're needed.      *)
  250. (* Screen and Window are opened.                                           *)
  251.  
  252.   BEGIN
  253.     WITH NuScreen DO
  254.       width := IFFInfo.BMHD.scrnWidth;
  255.       IF width<IFFInfo.BMHD.width THEN
  256.         width := IFFInfo.BMHD.width;
  257.       END;
  258.       height := IFFInfo.BMHD.scrnHeight;
  259.       IF height<IFFInfo.BMHD.height THEN
  260.         height := IFFInfo.BMHD.height;
  261.       END;
  262.       leftEdge := IFFInfo.BMHD.left;
  263.       topEdge := IFFInfo.BMHD.top;
  264.       depth := IFFInfo.BMHD.depth;
  265.       viewModes := ViewModeSet{};
  266.       IF (width>400) AND (depth<5) THEN INCL(viewModes,hires) END;
  267.       IF height>300 THEN INCL(viewModes,lace) END;
  268.       IF Lace  IN IFFInfo.CAMG.viewType THEN INCL(viewModes,lace  ) END;
  269.       IF HoMod IN IFFInfo.CAMG.viewType THEN INCL(viewModes,ham   ) END;
  270.       IF Hires IN IFFInfo.CAMG.viewType THEN INCL(viewModes,hires ) END;
  271.       IF DblPF IN IFFInfo.CAMG.viewType THEN INCL(viewModes,dualpf) END;
  272.       IF (ViewTypeSet{} = (ViewTypeSet{DblPF,HoMod} * IFFInfo.CAMG.viewType))
  273.          AND (depth=6) THEN
  274.         INCL(viewModes,extraHalfbrite);
  275.       END;
  276.       detailPen := 0; blockPen := 0;
  277.       type := customScreen+ScreenFlagSet{screenQuiet};
  278.       font := NIL;
  279.       defaultTitle := NIL;
  280.       gadgets := NIL;
  281.       customBitMap := NIL;
  282.       IF NOT(front IN Flags) THEN topEdge := 600 END;
  283.     END;
  284.     IF dontopen IN Flags THEN
  285.       INCL(NuScreen.type,customBitMap);
  286.       WITH NuScreen DO
  287.         customBitMap := AllocMem(SIZE(BitMap),MemReqSet{public});
  288.         InitBitMap(customBitMap^,depth,width,height);
  289.         i:=0;
  290.         REPEAT
  291.           customBitMap^.planes[i] := AllocRaster(width,height);
  292.           BitMaps[i] := customBitMap^.planes[i];
  293.           IF BitMaps[i]=NIL THEN
  294.             NoErr:=FALSE
  295.           ELSE
  296.             BltClear(BitMaps[i],width DIV 8 * height,0);
  297.           END;
  298.           INC(i);
  299.         UNTIL (i=depth) OR NOT(NoErr);
  300.         IF NOT(NoErr) THEN (* error: give allocated Mem back: *)
  301.           WHILE i>1 DO
  302.             DEC(i);
  303.             FreeRaster(BitMaps[i],width,height);
  304.           END;
  305.         END;
  306.       END;
  307.     ELSE
  308.       Screen := OpenScreen(NuScreen);
  309.       IF Screen=NIL THEN
  310.         NoErr := FALSE;
  311.       ELSE
  312.         IF NOT(front IN Flags) THEN
  313.           ScreenToBack(Screen);
  314.           MoveScreen(Screen,0,-600);
  315.         END;
  316.         BM := Screen^.rastPort.bitMap;
  317.         FOR i:=0 TO NuScreen.depth-1 DO
  318.           BitMaps[i] := BM^.planes[i];
  319.         END;
  320.         WITH IFFInfo.CMAP DO
  321.           FOR i:=0 TO colorCnt-1 DO
  322.             SetRGB4(ADR(Screen^.viewPort),i,red[i],green[i],blue[i]);
  323.           END;
  324.         END;
  325.       END;
  326.     END;
  327.     WITH NuWindow DO
  328.       leftEdge := 0;
  329.       topEdge := 0;
  330.       width := IFFInfo.BMHD.width;
  331.       height := IFFInfo.BMHD.height;
  332.       detailPen := 1;
  333.       blockPen := 0;
  334.       idcmpFlags := IDCMPFlagSet{};
  335.       flags := WindowFlagSet{borderless,noCareRefresh};
  336.       firstGadget := NIL;
  337.       checkMark := NIL;
  338.       title := NIL;
  339.       screen := Screen;
  340.       bitMap := NIL;
  341.       type := customScreen;
  342.     END;
  343.     IF (window IN Flags) AND (Screen#NIL) THEN
  344.       Window := OpenWindow(NuWindow);
  345.       IF Window=NIL THEN
  346.         CloseScreen(Screen);
  347.         Screen := NIL;
  348.         NoErr := FALSE;
  349.       END;
  350.     END;
  351.     IF NOT(visible IN Flags) THEN OffDisplay() END;
  352.   END OpenScrn;
  353.  
  354. PROCEDURE ReadQuick(To: ADDRESS; Count: CARDINAL);
  355.  
  356.   VAR
  357.     ToPtr: POINTER TO ARRAY[0..9999] OF UByte;
  358.     i: CARDINAL;
  359.  
  360.   BEGIN
  361.     ToPtr := To;
  362.     i := 0;
  363.     REPEAT
  364.       IF RQPos=RQLen THEN
  365.         RQLen := Read(InH,RQBuffer,512);
  366.         RQPos := 0;
  367.       END;
  368.       ToPtr^[i] := ORD(RQBuffer^[RQPos]);
  369.       INC(RQPos); INC(i);
  370.     UNTIL i=Count;
  371.   END ReadQuick;
  372.  
  373. BEGIN
  374.   IFFInfo.IFFTitle := IFFTitleSet{};
  375.  
  376.   IF NOT(visible IN Flags) THEN OffDisplay() END;
  377.   NoErr := TRUE; Screen := NIL; Window := NIL;
  378.   RQPos := 0; RQLen := 0;
  379.  
  380.   InH := Open(ADR(name),oldFile);
  381.   IF InH=NIL THEN NoErr := FALSE END;
  382.  
  383.   IF NoErr THEN
  384.  
  385. (*------  File Header:  ------*)
  386.  
  387.     len := Read(InH,Buffer,12);
  388.     IF (len=NIL) OR (Compare(TextBuffer^[0],first,4,"FORM",TRUE)#0) OR
  389.     (Compare(TextBuffer^[2],first,4,"ILBM",TRUE)#0) THEN NoErr := FALSE END;
  390.  
  391.     Exit := FALSE;
  392.  
  393. (*------  Main Loop:  ------*)
  394.  
  395.     WHILE NoErr AND NOT(Exit) DO
  396.       len := Read(InH,Buffer,4);
  397.  
  398.   (*------  BMHD:  ------*)
  399.  
  400.       IF Compare(TextBuffer^[0],first,4,"BMHD",TRUE)=0 THEN
  401.         INCL(IFFInfo.IFFTitle,BMHD);
  402.         len := Read(InH,Buffer,4);
  403.         len := Read(InH,Buffer,LONGBuffer^[0]);
  404.         WITH IFFInfo.BMHD DO
  405.           width     := WORDBuffer^[0];
  406.           height    := WORDBuffer^[1];
  407.           left      := WORDBuffer^[2];
  408.           top       := WORDBuffer^[3];
  409.           depth     := BYTEBuffer^[8];
  410.           masking   := BYTEBuffer^[9];
  411.           MaskPlane := masking=1;
  412.           Compression := BYTEBuffer^[10]=1;
  413.           transCol  := WORDBuffer^[6];
  414.           xAspect   := BYTEBuffer^[14];
  415.           yAspect   := BYTEBuffer^[15];
  416.           scrnWidth := WORDBuffer^[8];
  417.           scrnHeight:= WORDBuffer^[9];
  418.         END;
  419.  
  420.   (*------  CMAP:  ------*)
  421.  
  422.       ELSIF Compare(TextBuffer^[0],first,4,"CMAP",TRUE)=0 THEN
  423.         INCL(IFFInfo.IFFTitle,CMAP);
  424.         len := Read(InH,Buffer,4);
  425.         i := LONGBuffer^[0];
  426.         len := Read(InH,Buffer,i);
  427.         WITH IFFInfo.CMAP DO
  428.           colorCnt := i DIV 3;
  429.           j := 0;
  430.           FOR k:=0 TO colorCnt DO
  431.             red  [k] := SHIFT(BYTEBuffer^[j  ],-4);
  432.             green[k] := SHIFT(BYTEBuffer^[j+1],-4);
  433.             blue [k] := SHIFT(BYTEBuffer^[j+2],-4);
  434.             INC(j,3);
  435.           END;
  436.           INC(colorCnt);
  437.         END;
  438.  
  439.   (*------  CAMG:  ------*)
  440.  
  441.       ELSIF Compare(TextBuffer^[0],first,4,"CAMG",TRUE)=0 THEN
  442.         INCL(IFFInfo.IFFTitle,CAMG);
  443.         len := Read(InH,Buffer,8);
  444.         IFFInfo.CAMG.viewType := CAST(ViewTypeSet,LONGBuffer^[1]);
  445.  
  446.   (*------  GRAB:  ------*)
  447.  
  448.       ELSIF Compare(TextBuffer^[0],first,4,"GRAB",TRUE)=0 THEN
  449.         INCL(IFFInfo.IFFTitle,GRAB);
  450.         len := Read(InH,Buffer,8);
  451.         IFFInfo.GRAB.hotX := WORDBuffer^[2];
  452.         IFFInfo.GRAB.hotY := WORDBuffer^[3];
  453.  
  454.   (*------  DEST:  ------*)
  455.  
  456.       ELSIF Compare(TextBuffer^[0],first,4,"DEST",TRUE)=0 THEN
  457.         INCL(IFFInfo.IFFTitle,DEST);
  458.         len := Read(InH,Buffer,12);
  459.         WITH IFFInfo.DEST DO
  460.           depth      := BYTEBuffer^[4];
  461.           planePick  := WORDBuffer^[3];
  462.           planeOnOff := WORDBuffer^[4];
  463.           planeMask  := WORDBuffer^[5];
  464.         END;
  465.  
  466.   (*------  CRNG:  ------*)
  467.  
  468.       ELSIF Compare(TextBuffer^[0],first,4,"CRNG",TRUE)=0 THEN
  469.         IF NOT(CRNG IN IFFInfo.IFFTitle) THEN
  470.           IFFInfo.CRNG.count := 0;
  471.         END;
  472.         INCL(IFFInfo.IFFTitle,CRNG);
  473.         len := Read(InH,Buffer,12);
  474.         WITH IFFInfo.CRNG.data[IFFInfo.CRNG.count] DO
  475.           rate := WORDBuffer^[3];
  476.           on   := 0 IN CAST(BITSET,WORDBuffer^[4]);
  477.           forward := NOT(1 IN CAST(BITSET,WORDBuffer^[4]));
  478.           low  := BYTEBuffer^[10];
  479.           high := BYTEBuffer^[11];
  480. (* this line is only to identify illegal data, that some IFF-Files contain:*)
  481.           on := on AND (low<IFFInfo.CMAP.colorCnt)
  482.                 AND (high<IFFInfo.CMAP.colorCnt);
  483.         END;
  484.         INC(IFFInfo.CRNG.count);
  485.  
  486.   (*------  BODY:  ------*)
  487.  
  488.       ELSIF Compare(TextBuffer^[0],first,4,"BODY",TRUE)=0 THEN
  489.         OpenScrn();
  490.         IF NoErr THEN
  491.           len := Read(InH,Buffer,4);
  492.           LineLength := SHIFT(SHIFT(CAST(INTEGER,CAST(BITSET,
  493.                         IFFInfo.BMHD.width+15) * {4..15}),-4),1);
  494.           LineWidth  := SHIFT(NuScreen.width,-3);
  495.           IF Compression THEN
  496.           (*------  let's load the BitMap's Data:  ------*)
  497.             LoadBody(Read512, RQBuffer, ADR(BitMaps[0]), LineLength,
  498.                      LineWidth, IFFInfo.BMHD.height, NuScreen.depth,
  499.                      MaskPlane); (* this does all the work very quickly *)
  500.           ELSE   (* not compressed *)
  501.           (*------  to load uncompressed Images is less time-critical: *)
  502.             FOR Line := 0 TO IFFInfo.BMHD.height-1 DO
  503.               FOR Plane := 0 TO NuScreen.depth-1 DO
  504.                 ReadQuick(BitMaps[Plane]+ LineWidth*Line,LineLength);
  505.               END;
  506.               IF MaskPlane THEN
  507.                 ReadQuick(Buffer,LineLength);
  508.               END;
  509.             END;
  510.           END;
  511.         END; (* IF NoErr *)
  512.         Exit := TRUE;
  513.  
  514.   (*------  Ignore unknown data:  ------*)
  515.  
  516.       ELSE
  517.         len := Read(InH,Buffer,4);
  518.         i := LONGBuffer^[0];
  519.         WHILE i>256 DO
  520.           len := Read(InH,Buffer,256);
  521.           DEC(i,256);
  522.         END;
  523.         len := Read(InH,Buffer,i);
  524.       END;
  525.  
  526.     END;   (* WHILE NOT(Exit DO *)
  527.   END;   (* IF NoErr *)
  528.  
  529.   IF InH#NIL THEN Close(InH); InH := NIL; END;
  530.   IF NOT(NoErr) THEN
  531.     IF Window#NIL THEN CloseWindow(Window) END;
  532.     IF Screen#NIL THEN CloseScreen(Screen) END;
  533.   END;
  534.   OnDisplay();
  535.   RETURN NoErr;
  536. END ReadILBM; (* that's it *)
  537.  
  538. (*---------------  Procedures for ColorCycling:  --------------------------*)
  539.  
  540. PROCEDURE CycleInterrupt();
  541.  
  542. BEGIN
  543.   INLINE(MOVEMS,3F3EH);
  544.  
  545.   IntInfo := ADDRESS(REG(9));
  546.   IF CRNG IN IntInfo^.IFFTitle THEN
  547.     IntNum := IntInfo^.Internal.CycleID;
  548.     WITH CycleInfos[IntNum] DO
  549.       IntCount := 0;
  550.       WHILE IntCount<IntInfo^.CRNG.count DO
  551.         WITH IntInfo^.CRNG.data[IntCount] DO
  552.           IF on THEN
  553.             INC(speedCnt[IntCount],rate);
  554.             IF speedCnt[IntCount]>=4000H THEN
  555.               (* this 4000H should have been 8000H, but then it's to slow. *)
  556.               (* dont know why, but this way, it works correctly           *)
  557.               DEC(speedCnt[IntCount],4000H);
  558.               IF forward THEN
  559.                 IF count[IntCount]<=low THEN
  560.                   count[IntCount]:=high;
  561.                 ELSE
  562.                   DEC(count[IntCount]);
  563.                 END;
  564.               ELSE
  565.                 IF count[IntCount]>=high THEN
  566.                   count[IntCount]:=low;
  567.                 ELSE
  568.                   INC(count[IntCount]);
  569.                 END;
  570.               END;
  571.               IntCount3 := count[IntCount];
  572.               IntCount2 := low;
  573.               WHILE IntCount2<=high DO
  574.                 SetRGB4(VP,IntCount2,IntInfo^.CMAP.red[IntCount3],
  575.                                      IntInfo^.CMAP.green[IntCount3],
  576.                                      IntInfo^.CMAP.blue[IntCount3]);
  577.                 INC(IntCount3);
  578.                 IF IntCount3>high THEN IntCount3:=low END;
  579.                 INC(IntCount2);
  580.               END;
  581.             END;
  582.           END;
  583.         END;
  584.         INC(IntCount);
  585.       END;
  586.     END;
  587.   END;
  588.  
  589.   INLINE(MOVEML,7CFCH);
  590. END CycleInterrupt;
  591.  
  592. PROCEDURE DoCycle(Info: IFFInfoTypePtr; Screen: ScreenPtr): BOOLEAN;
  593. (* this creates an interrupt, that does cycling. You needn't worry,        *)
  594. (* whether there's cycling data or not. Don't forget to call EndCycle to   *)
  595. (* remove the Cycling-Interrupt !!!                                        *)
  596. (* If result is false, any error occured. Don't call EndCycle in this case!*)
  597.  
  598. BEGIN
  599.   i:=0;
  600.   LOOP
  601.     IF CycleInfos[i].VP=NIL THEN EXIT END;
  602.     INC(i);
  603.     IF i=32 THEN RETURN FALSE END;
  604.   END;
  605.   Info^.Internal.CycleID := i;
  606.   WITH CycleInfos[i] DO
  607.     VP := ADR(Screen^.viewPort);
  608.     IF CRNG IN Info^.IFFTitle THEN
  609.       FOR j:=0 TO Info^.CRNG.count-1 DO
  610.         count[j] := Info^.CRNG.data[j].low;
  611.         speedCnt[j] := 0;
  612.       END;
  613.     END;
  614.     WITH int DO
  615.       node.type := interrupt;
  616.       node.pri  := -60;
  617.       node.name := NIL;
  618.       data := Info;
  619.       code := ADR(CycleInterrupt);
  620.     END;
  621.     AddIntServer(vertb,ADR(int));
  622.   END;
  623.   RETURN TRUE;
  624. END DoCycle;
  625.  
  626. PROCEDURE EndCycle(Info: IFFInfoTypePtr);
  627. (* remove cycling-Interrupt                                                *)
  628.  
  629. BEGIN
  630.   i := Info^.Internal.CycleID;
  631.   RemIntServer(vertb,ADR(CycleInfos[i].int));
  632.   CycleInfos[i].VP := NIL;
  633. END EndCycle;
  634.  
  635. (*------------------------  TermProcedure:  -------------------------------*)
  636.  
  637. PROCEDURE CleanUp();
  638.  
  639. BEGIN
  640.   IF myLevel>=CurrentLevel() THEN
  641.     IF InH#NIL THEN Close(InH) END;
  642.     FreeMem(Buffer,768);
  643.   END;
  644. END CleanUp;
  645.  
  646. (*-----------------------  Initialization:  -------------------------------*)
  647.  
  648. BEGIN
  649.   myLevel := CurrentLevel();
  650.   TermProcedure(CleanUp);
  651.   Buffer := AllocMem(768,MemReqSet{chip,memClear});
  652.   Assert(Buffer#NIL,ADR("Not enough ChipMem !!!"));
  653.   TextBuffer := Buffer;
  654.   LONGBuffer := Buffer;
  655.   WORDBuffer := Buffer;
  656.   BYTEBuffer := Buffer;
  657.   RQBuffer := ADDRESS(Buffer+256);
  658.   InH := NIL;
  659.   FOR i:=0 TO 31 DO CycleInfos[i].VP:=NIL END;
  660.  
  661. END IFFLoad.
  662.